#include <Riostream.h>
#include <TVirtualMC.h>
#include <TLorentzVector.h>
#include <TTree.h>
#include <math.h> 
#include <cstdlib>
#include <map>

#include "sPHENIX_PreshowerSD.h"
#include "sPHENIX_CalorimeterHit.h"
#include "sPHENIX_RootManager.h"

/// \cond CLASSIMP
ClassImp(sPHENIX_PreshowerSD)
/// \endcond
 
using namespace std;
 
//_____________________________________________________________________________
sPHENIX_PreshowerSD::sPHENIX_PreshowerSD(const char* name, 
                                     sPHENIX_DetectorConstruction* detector)
  : TNamed(name, ""),
    Detector(detector),
    SensingMatVolId(0),
    VerboseLevel(1),    // 1 For PrintTotal, 2 for Print
    counter(0)
{

  /// Standard constructor.
  /// Create hits collection and an empty hit for each layer
  /// As the copy numbers may start from 0 or 1 (depending on
  /// geometry model, we create one more layer for this case.)
  /// \param name      The calorimeter hits collection name
  /// \param detector  The detector construction
}
 
//_____________________________________________________________________________
sPHENIX_PreshowerSD::sPHENIX_PreshowerSD()
  : TNamed(),
    Detector(0),
    SensingMatVolId(0),
    VerboseLevel(0),
    counter(0)
{
  /// Default constructor
}
 
//_____________________________________________________________________________
sPHENIX_PreshowerSD::~sPHENIX_PreshowerSD()
{
  /// Destructor
 
  //  if (PreshowerCollection) PreshowerCollection.Delete();
  //  delete PreshowerCollection;
}
 
//
// private methods
//

//_____________________________________________________________________________
void  sPHENIX_PreshowerSD::ResetHits()
{
  /// Reset all hits in the hits collection.

  PreshowerTowerEdepCol.clear(); 
} 
 
//
// public methods
//
 
//_____________________________________________________________________________
void sPHENIX_PreshowerSD::Initialize()
{
  /// Register hits collection in the Root manager;
  /// set sensitive volumes.
   
  Register();
 
  SensingMatVolId = gMC->VolId("preshowertowervol");
  /*
  if ( SensingMatVolId == 0 ) {
    // Volume names are different in sPHENIX detector construction
    SensingMatVolId = gMC->VolId("SensingMat");
  }  
  */
}
 
//_____________________________________________________________________________
Bool_t sPHENIX_PreshowerSD::ProcessHits()
{
  /// Account energy deposit and track lengths for each layer in its hit.
 
  Int_t towerCopyNo;
  Int_t id = gMC->CurrentVolID(towerCopyNo);

  if (id != SensingMatVolId ) 
    return false;

  Double_t edep = gMC->Edep();

  if (id == SensingMatVolId && edep != 0) { 

    sPHENIX_CalorimeterHit* newHit = new sPHENIX_CalorimeterHit();
    pair<map<int,sPHENIX_CalorimeterHit*>::iterator,bool> ret = PreshowerTowerEdepCol.insert(pair<int,sPHENIX_CalorimeterHit*>(towerCopyNo,newHit));
    PreshowerTowerEdepCol[towerCopyNo]->AddEdep(edep);
    if (ret.second == true) { // first time the tower is added
      // Add the other tower information...
    } 
 
  }

  return true;
}
 
//_____________________________________________________________________________
void sPHENIX_PreshowerSD::EndOfEvent()
{
  /// Print hits collection (if verbose) and reset hits afterwards.
 
  if (VerboseLevel>1)  Print();
  else if(VerboseLevel>0)  PrintTotal();


  // Reset hits collection
  ResetHits();  
}
 
//_____________________________________________________________________________
void sPHENIX_PreshowerSD::Register()
{
  /// Register the hits collection in Root manager.
  
  PreshowerTowerEdepColPtr = &PreshowerTowerEdepCol;
  sPHENIX_RootManager::Instance()
    ->Register("preshowerhits", "std::map<int,sPHENIX_CalorimeterHit*>", &PreshowerTowerEdepColPtr);
}
 
//_____________________________________________________________________________
void sPHENIX_PreshowerSD::Print(Option_t* /*option*/) const
{
  /// Print the hits collection.
             
  //for (Int_t i=0; i<PreshowerCollection.size(); i++) PreshowerCollection[i]->Print();          
}
 
//_____________________________________________________________________________
void sPHENIX_PreshowerSD::PrintTotal() const
{
  /// Print the total values for all layers.
  /*
  Double_t totESensingMat=0.;
  Double_t totLSensingMat=0.;
 
  Int_t nofHits = PreshowerCollection.size();
  for (Int_t i=0; i<nofHits; i++) {
    totESensingMat += GetHit(i)->GetEdepSensingMat(); 
    totLSensingMat += GetHit(i)->GetTrakSensingMat();
  }

  cout << "   SensingMat:      total energy (MeV): " 
       << setw(7) << totESensingMat * 1.0e03
       << "       total track length (cm):  "
       << setw(7) << totLSensingMat
       << endl;
  */
}
